#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cctype>
#include <unordered_map>
#include <memory>
#include <algorithm>
#include <stdexcept>
#include <utility>
#include <unordered_set>
using namespace std;

enum class ValueType {
    INTEGER,
    FLOAT,
    STRING,
    BOOL,
    NULL_,
    UNKNOWN
};
enum class TokenType {
    INT_TYPE,
    FLOAT_TYPE,
    STRING_TYPE,
    BOOL_TYPE, 
    NULL_TYPE,

    INTEGER,  
    FLOAT,     
    STRING,   
    BOOL,   
    NULL_,    
    IDENTIFIER, 
    PRINT,  
    ASSERT,    
    LET,  
    CONST,    
    INPUT, 
    LEN,      
    SIZEOF,   
    IS,       
    AS,     

    PLUS,       
    MINUS,      
    STAR,     
    SLASH,   
    PERCENT,  
    LSHIFT, 
    RSHIFT, 
    URSHIFT,
    SPACESHIP,
    EQUAL, 
    NOT_EQUAL,
    STRICT_EQUAL,
    STRICT_NOT_EQUAL, 
    LESS,      
    GREATER,   
    LESS_EQUAL, 
    GREATER_EQUAL, 
    ASSIGN,  
    QUESTION, 
    COLON,    
    BIT_AND,  
    BIT_OR,  
    BIT_XOR, 
    BIT_NOT,  

    LPAREN,     
    RPAREN,     
    SEMICOLON,  
    COMMENT,    
    END         
};

struct Token {
    TokenType type;
    string value;
    size_t line;
    size_t column;

    Token(TokenType type, string value, size_t line, size_t column)
        : type(type), value(std::move(value)), line(line), column(column) {}
};

class Lexer {
public:
    explicit Lexer(const string& source) : source(source), pos(0), line(1), column(1), filename("input") {}

    vector<Token> tokenize() {
        vector<Token> tokens;
        while (pos < source.length()) {
            char current = peek();

            if (isspace(current)) {
                consume();
                continue;
            }

            if (current == '/' && peek(1) == '/') {
                tokens.push_back(scanLineComment());
                continue;
            }

            if (current == '/' && peek(1) == '*') {
                tokens.push_back(scanBlockComment());
                continue;
            }

            if (isalpha(current) || current == '_') {
                tokens.push_back(scanKeywordOrIdentifier());
                continue;
            }

            if (isdigit(current)) {
                tokens.push_back(scanNumber());
                continue;
            }

            if (current == '"') {
                tokens.push_back(scanString());
                continue;
            }

            if (isOperator(current)) {
                tokens.push_back(scanOperator());
                continue;
            }

            switch (current) {
                case '(':
                    tokens.emplace_back(TokenType::LPAREN, "(", line, column);
                    consume();
                    break;
                case ')':
                    tokens.emplace_back(TokenType::RPAREN, ")", line, column);
                    consume();
                    break;
                case ';':
                    tokens.emplace_back(TokenType::SEMICOLON, ";", line, column);
                    consume();
                    break;
                case ':':
                    tokens.emplace_back(TokenType::COLON, ":", line, column);
                    consume();
                    break;
                case '?':
                    tokens.emplace_back(TokenType::QUESTION, "?", line, column);
                    consume();
                    break;
                default:
                    throw runtime_error("Unexpected character at line " + to_string(line) +
                                      ", column " + to_string(column) + ": " + current);
            }
        }

        tokens.emplace_back(TokenType::END, "", line, column);
        return tokens;
    }

    void setFilename(const string& name) {
        filename = name;
    }

private:
    string source;
    size_t pos;
    size_t line;
    size_t column;
    string filename;

    char peek(size_t ahead = 0) const {
        if (pos + ahead >= source.length()) return '\0';
        return source[pos + ahead];
    }

    void consume() {
        if (peek() == '\n') {
            line++;
            column = 1;
        } else {
            column++;
        }
        pos++;
    }

    Token scanLineComment() {
        size_t startLine = line;
        size_t startColumn = column;
        string value;

        value += peek(); consume();
        value += peek(); consume();

        while (peek() != '\n' && peek() != '\0') {
            value += peek();
            consume();
        }

        return Token(TokenType::COMMENT, value, startLine, startColumn);
    }

    Token scanBlockComment() {
        size_t startLine = line;
        size_t startColumn = column;
        string value;

        value += peek(); consume();
        value += peek(); consume();

        while (!(peek() == '*' && peek(1) == '/') && peek() != '\0') {
            value += peek();
            consume();
        }

        if (peek() == '\0') {
            throw runtime_error("Unterminated block comment at line " + to_string(startLine));
        }

        value += peek(); consume();
        value += peek(); consume();

        return Token(TokenType::COMMENT, value, startLine, startColumn);
    }

    Token scanKeywordOrIdentifier() {
        size_t startLine = line;
        size_t startColumn = column;
        string value;

        while (isalnum(peek()) || peek() == '_') {
            value += peek();
            consume();
        }
        if (value == "__LINE__") {
            return Token(TokenType::INTEGER, to_string(startLine), startLine, startColumn);
        }
        if (value == "__FILE__") {
            return Token(TokenType::STRING, "\"" + filename + "\"", startLine, startColumn);
        }

        if (value == "print") {
            return Token(TokenType::PRINT, value, startLine, startColumn);
        } else if (value == "assert") {
            return Token(TokenType::ASSERT, value, startLine, startColumn);
        } else if (value == "let") {
            return Token(TokenType::LET, value, startLine, startColumn);
        } else if (value == "const") {
            return Token(TokenType::CONST, value, startLine, startColumn);
        } else if (value == "true" || value == "false") {
            return Token(TokenType::BOOL, value, startLine, startColumn);
        } else if (value == "null") {
            return Token(TokenType::NULL_, value, startLine, startColumn);
        } else if (value == "int") {
            return Token(TokenType::INT_TYPE, value, startLine, startColumn);
        } else if (value == "float") {
            return Token(TokenType::FLOAT_TYPE, value, startLine, startColumn);
        } else if (value == "string") {
            return Token(TokenType::STRING_TYPE, value, startLine, startColumn);
        } else if (value == "bool") {
            return Token(TokenType::BOOL_TYPE, value, startLine, startColumn);
        } else if (value == "input") {
            return Token(TokenType::INPUT, value, startLine, startColumn);
        } else if (value == "len") {
            return Token(TokenType::LEN, value, startLine, startColumn);
        } else if (value == "sizeof") {
            return Token(TokenType::SIZEOF, value, startLine, startColumn);
        } else if (value == "is") {
            return Token(TokenType::IS, value, startLine, startColumn);
        } else if (value == "as") {
            return Token(TokenType::AS, value, startLine, startColumn);
        }

        return Token(TokenType::IDENTIFIER, value, startLine, startColumn);
    }

    Token scanNumber() {
        size_t startLine = line;
        size_t startColumn = column;
        string value;
        bool isFloat = false;

        while (isdigit(peek()) || peek() == '.') {
            if (peek() == '.') {
                if (isFloat) {
                    throw runtime_error("Invalid number format at line " + to_string(line) +
                                      ", column " + to_string(column));
                }
                isFloat = true;
            }
            value += peek();
            consume();
        }

        if (isalpha(peek())) {
            throw runtime_error("Invalid number format at line " + to_string(line) +
                              ", column " + to_string(column));
        }

        return Token(isFloat ? TokenType::FLOAT : TokenType::INTEGER, value, startLine, startColumn);
    }

    Token scanString() {
        size_t startLine = line;
        size_t startColumn = column;
        string value;

        consume();

        while (peek() != '"' && peek() != '\0') {
            if (peek() == '\\') {
                consume();
                switch (peek()) {
                    case 'n': value += '\n'; break;
                    case 't': value += '\t'; break;
                    case 'r': value += '\r'; break;
                    case '"': value += '"'; break;
                    case '\\': value += '\\'; break;
                    default:
                        throw runtime_error("Invalid escape sequence at line " + to_string(line) +
                                          ", column " + to_string(column));
                }
                consume();
            } else {
                value += peek();
                consume();
            }
        }

        if (peek() == '\0') {
            throw runtime_error("Unterminated string at line " + to_string(startLine));
        }

        consume();

        return Token(TokenType::STRING, value, startLine, startColumn);
    }

    Token scanOperator() {
        size_t startLine = line;
        size_t startColumn = column;
        char current = peek();

        switch (current) {
            case '+':
                consume();
                return Token(TokenType::PLUS, "+", startLine, startColumn);
            case '-':
                consume();
                return Token(TokenType::MINUS, "-", startLine, startColumn);
            case '*':
                consume();
                return Token(TokenType::STAR, "*", startLine, startColumn);
            case '/':
                consume();
                return Token(TokenType::SLASH, "/", startLine, startColumn);
            case '%':
                consume();
                return Token(TokenType::PERCENT, "%", startLine, startColumn);
            case '&':
                consume();
                return Token(TokenType::BIT_AND, "&", startLine, startColumn);
            case '|':
                consume();
                return Token(TokenType::BIT_OR, "|", startLine, startColumn);
            case '^':
                consume();
                return Token(TokenType::BIT_XOR, "^", startLine, startColumn);
            case '~':
                consume();
                return Token(TokenType::BIT_NOT, "~", startLine, startColumn);
            case '=':
                if (peek(1) == '=') {
                    consume(); consume();
                    if (peek() == '=') {
                        consume();
                        return Token(TokenType::STRICT_EQUAL, "===", startLine, startColumn);
                    }
                    return Token(TokenType::EQUAL, "==", startLine, startColumn);
                }
                consume();
                return Token(TokenType::ASSIGN, "=", startLine, startColumn);
            case '!':
                if (peek(1) == '=') {
                    consume(); consume();
                    if (peek() == '=') {
                        consume();
                        return Token(TokenType::STRICT_NOT_EQUAL, "!==", startLine, startColumn);
                    }
                    return Token(TokenType::NOT_EQUAL, "!=", startLine, startColumn);
                }
                throw runtime_error("Unexpected operator at line " + to_string(line) +
                                  ", column " + to_string(column) + ": !");
            case '<':
                if (peek(1) == '<') {
                    consume(); consume();
                    return Token(TokenType::LSHIFT, "<<", startLine, startColumn);
                } else if (peek(1) == '=') {
                    if (peek(2) == '>') {
                        consume(); consume(); consume();
                        return Token(TokenType::SPACESHIP, "<=>", startLine, startColumn);
                    } else {
                        consume(); consume();
                        return Token(TokenType::LESS_EQUAL, "<=", startLine, startColumn);
                    }
                }
                consume();
                return Token(TokenType::LESS, "<", startLine, startColumn);
            case '>':
                if (peek(1) == '>') {
                    if (peek(2) == '>') {
                        consume(); consume(); consume();
                        return Token(TokenType::URSHIFT, ">>>", startLine, startColumn);
                    } else {
                        consume(); consume();
                        return Token(TokenType::RSHIFT, ">>", startLine, startColumn);
                    }
                } else if (peek(1) == '=') {
                    consume(); consume();
                    return Token(TokenType::GREATER_EQUAL, ">=", startLine, startColumn);
                }
                consume();
                return Token(TokenType::GREATER, ">", startLine, startColumn);
            default:
                throw runtime_error("Unexpected operator at line " + to_string(line) +
                                  ", column " + to_string(column) + ": " + current);
        }
    }

    bool isOperator(char c) const {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '%' ||
               c == '<' || c == '>' || c == '=' || c == '!' ||
               c == '&' || c == '|' || c == '^' || c == '~';
    }
};
class ASTNode {
public:
    virtual ~ASTNode() = default;
    virtual string generateC() const = 0;
};
class Expression : public ASTNode {
public:
    virtual ValueType getType() const = 0;
    virtual string getCType() const = 0;
};
class Literal : public Expression {
public:
    Token token;
    ValueType type;

    explicit Literal(const Token& token) : token(token), type(getTypeFromToken(token.type)) {}

    string generateC() const override {
        switch (token.type) {
            case TokenType::INTEGER:
            case TokenType::FLOAT:
                return token.value;
            case TokenType::STRING:
                return token.value; // 已经包含引号
            case TokenType::BOOL:
                return token.value == "true" ? "1" : "0";
            case TokenType::NULL_:
                return "NULL";
            default:
                throw runtime_error("Invalid literal type");
        }
    }

    ValueType getType() const override {
        return type;
    }

    string getCType() const override {
        switch (type) {
            case ValueType::INTEGER: return "int";
            case ValueType::FLOAT: return "double";
            case ValueType::STRING: return "char*";
            case ValueType::BOOL: return "int";
            case ValueType::NULL_: return "void*";
            default: return "int";
        }
    }

private:
    static ValueType getTypeFromToken(TokenType type) {
        switch (type) {
            case TokenType::INTEGER: return ValueType::INTEGER;
            case TokenType::FLOAT: return ValueType::FLOAT;
            case TokenType::STRING: return ValueType::STRING;
            case TokenType::BOOL: return ValueType::BOOL;
            case TokenType::NULL_: return ValueType::NULL_;
            default: return ValueType::UNKNOWN;
        }
    }
};
class BuiltinCall : public Expression {
public:
    TokenType func;
    unique_ptr<Expression> arg;

    BuiltinCall(TokenType func, unique_ptr<Expression> arg)
        : func(func), arg(std::move(arg)) {}

    string generateC() const override {
        switch (func) {
            case TokenType::INPUT:
                return "input()";
            case TokenType::LEN:
                return "strlen(" + arg->generateC() + ")";
            case TokenType::SIZEOF:
                return "sizeof(" + arg->getCType() + ")";
            default:
                throw runtime_error("Unknown builtin function");
        }
    }

    ValueType getType() const override {
        switch (func) {
            case TokenType::INPUT: return ValueType::STRING;
            case TokenType::LEN: return ValueType::INTEGER;
            case TokenType::SIZEOF: return ValueType::INTEGER;
            default: return ValueType::UNKNOWN;
        }
    }

    string getCType() const override {
        switch (getType()) {
            case ValueType::INTEGER: return "int";
            case ValueType::STRING: return "char*";
            default: return "int";
        }
    }
};
class VariableDeclaration : public ASTNode {
public:
    bool isConst;
    string identifier;
    ValueType declaredType;
    bool hasTypeAnnotation;
    unique_ptr<Expression> initializer;

    VariableDeclaration(bool isConst, string identifier,
                       ValueType declaredType, bool hasTypeAnnotation,
                       unique_ptr<Expression> initializer)
        : isConst(isConst), identifier(std::move(identifier)),
          declaredType(declaredType), hasTypeAnnotation(hasTypeAnnotation),
          initializer(std::move(initializer)) {}

    string generateC() const override {
        string typeStr;
        if (hasTypeAnnotation) {
            switch (declaredType) {
                case ValueType::INTEGER: typeStr = "int"; break;
                case ValueType::FLOAT: typeStr = "double"; break;
                case ValueType::STRING: typeStr = "char*"; break;
                case ValueType::BOOL: typeStr = "int"; break;
                case ValueType::NULL_: typeStr = "void*"; break;
                default: typeStr = "int"; break;
            }
        } else {
            switch (initializer->getType()) {
                case ValueType::INTEGER: typeStr = "int"; break;
                case ValueType::FLOAT: typeStr = "double"; break;
                case ValueType::STRING: typeStr = "char*"; break;
                case ValueType::BOOL: typeStr = "int"; break;
                case ValueType::NULL_: typeStr = "void*"; break;
                default: typeStr = "int"; break;
            }
        }

        string qualifier = isConst ? "const " : "";
        return qualifier + typeStr + " " + identifier + " = " + initializer->generateC() + ";";
    }
};
class VariableReference : public Expression {
public:
    string identifier;

    explicit VariableReference(string identifier) : identifier(std::move(identifier)) {}

    string generateC() const override {
        return identifier;
    }

    ValueType getType() const override {
        return ValueType::UNKNOWN;
    }

    string getCType() const override {
        return "int"; // 实际应从符号表获取
    }
};
class BinaryOperation : public Expression {
public:
    Token op;
    unique_ptr<Expression> left;
    unique_ptr<Expression> right;

    BinaryOperation(Token op, unique_ptr<Expression> left, unique_ptr<Expression> right)
        : op(op), left(std::move(left)), right(std::move(right)) {}

    string generateC() const override {
        if (op.type == TokenType::SPACESHIP) {
            return "(" + left->generateC() + " > " + right->generateC() + ") - (" +
                   left->generateC() + " < " + right->generateC() + ")";
        }

        string c_op;
        switch (op.type) {
            case TokenType::PLUS: c_op = "+"; break;
            case TokenType::MINUS: c_op = "-"; break;
            case TokenType::STAR: c_op = "*"; break;
            case TokenType::SLASH: c_op = "/"; break;
            case TokenType::PERCENT: c_op = "%"; break;
            case TokenType::LSHIFT: c_op = "<<"; break;
            case TokenType::RSHIFT: c_op = ">>"; break;
            case TokenType::BIT_AND: c_op = "&"; break;
            case TokenType::BIT_OR: c_op = "|"; break;
            case TokenType::BIT_XOR: c_op = "^"; break;
            case TokenType::URSHIFT:
                return "(unsigned)(" + left->generateC() + ") >> (" + right->generateC() + ")";
            case TokenType::EQUAL: c_op = "=="; break;
            case TokenType::NOT_EQUAL: c_op = "!="; break;
            case TokenType::STRICT_EQUAL:
                return "((typeof(" + left->generateC() + ") == typeof(" + right->generateC() + ")) && (" +
                       left->generateC() + " == " + right->generateC() + "))";
            case TokenType::STRICT_NOT_EQUAL:
                return "((typeof(" + left->generateC() + ") != typeof(" + right->generateC() + ")) || (" +
                       left->generateC() + " != " + right->generateC() + "))";
            case TokenType::LESS: c_op = "<"; break;
            case TokenType::GREATER: c_op = ">"; break;
            case TokenType::LESS_EQUAL: c_op = "<="; break;
            case TokenType::GREATER_EQUAL: c_op = ">="; break;
            default:
                throw runtime_error("Invalid binary operator");
        }
        return "(" + left->generateC() + " " + c_op + " " + right->generateC() + ")";
    }

    ValueType getType() const override {
        ValueType leftType = left->getType();
        ValueType rightType = right->getType();

        if (leftType == ValueType::NULL_ || rightType == ValueType::NULL_) {
            return ValueType::NULL_;
        }

        if (op.type == TokenType::PLUS &&
            (leftType == ValueType::STRING || rightType == ValueType::STRING)) {
            return ValueType::STRING;
        }

        if (op.type == TokenType::EQUAL || op.type == TokenType::NOT_EQUAL ||
            op.type == TokenType::STRICT_EQUAL || op.type == TokenType::STRICT_NOT_EQUAL ||
            op.type == TokenType::SPACESHIP || op.type == TokenType::LESS ||
            op.type == TokenType::GREATER || op.type == TokenType::LESS_EQUAL ||
            op.type == TokenType::GREATER_EQUAL) {
            return ValueType::BOOL;
        }

        if (op.type == TokenType::BIT_AND || op.type == TokenType::BIT_OR ||
            op.type == TokenType::BIT_XOR || op.type == TokenType::LSHIFT ||
            op.type == TokenType::RSHIFT || op.type == TokenType::URSHIFT) {
            return ValueType::INTEGER;
        }

        if (leftType == ValueType::FLOAT || rightType == ValueType::FLOAT) {
            return ValueType::FLOAT;
        }

        return leftType;
    }

    string getCType() const override {
        switch (getType()) {
            case ValueType::INTEGER: return "int";
            case ValueType::FLOAT: return "double";
            case ValueType::STRING: return "char*";
            case ValueType::BOOL: return "int";
            case ValueType::NULL_: return "void*";
            default: return "int";
        }
    }
};
class UnaryOperation : public Expression {
public:
    Token op;
    unique_ptr<Expression> expr;

    UnaryOperation(Token op, unique_ptr<Expression> expr)
        : op(op), expr(std::move(expr)) {}

    string generateC() const override {
        switch (op.type) {
            case TokenType::MINUS:
                return "(-" + expr->generateC() + ")";
            case TokenType::BIT_NOT:
                return "(~" + expr->generateC() + ")";
            default:
                throw runtime_error("Invalid unary operator");
        }
    }

    ValueType getType() const override {
        return expr->getType();
    }

    string getCType() const override {
        return expr->getCType();
    }
};
class TernaryOperation : public Expression {
public:
    unique_ptr<Expression> condition;
    unique_ptr<Expression> trueExpr;
    unique_ptr<Expression> falseExpr;

    TernaryOperation(unique_ptr<Expression> condition,
                   unique_ptr<Expression> trueExpr,
                   unique_ptr<Expression> falseExpr)
        : condition(std::move(condition)),
          trueExpr(std::move(trueExpr)),
          falseExpr(std::move(falseExpr)) {}

    string generateC() const override {
        return "(" + condition->generateC() + " ? " +
               trueExpr->generateC() + " : " +
               falseExpr->generateC() + ")";
    }

    ValueType getType() const override {
        ValueType trueType = trueExpr->getType();
        ValueType falseType = falseExpr->getType();

        if (trueType == ValueType::FLOAT || falseType == ValueType::FLOAT) {
            return ValueType::FLOAT;
        }
        return trueType;
    }

    string getCType() const override {
        string trueType = trueExpr->getCType();
        string falseType = falseExpr->getCType();

        if (trueType == "double" || falseType == "double") {
            return "double";
        }
        return trueType;
    }
};
class PrintStatement : public ASTNode {
public:
    unique_ptr<Expression> expression;

    explicit PrintStatement(unique_ptr<Expression> expression)
        : expression(std::move(expression)) {}

    string generateC() const override {
        string expr = expression->generateC();
        string format;
        string cast;

        switch (expression->getType()) {
            case ValueType::INTEGER:
                format = "%d";
                cast = "(int)";
                break;
            case ValueType::FLOAT:
                format = "%f";
                cast = "(double)";
                break;
            case ValueType::STRING:
                format = "%s";
                cast = "";
                break;
            case ValueType::BOOL:
                format = "%s";
                expr = expr + " ? \"true\" : \"false\"";
                cast = "";
                break;
            case ValueType::NULL_:
                return "printf(\"null\\n\");";
            default:
                format = "%d";
                cast = "(int)";
        }

        return "printf(\"" + format + "\\n\", " + cast + expr + ");";
    }
};
class AssertStatement : public ASTNode {
public:
    unique_ptr<Expression> expression;

    explicit AssertStatement(unique_ptr<Expression> expression)
        : expression(std::move(expression)) {}

    string generateC() const override {
        string expr = expression->generateC();
        return "if (!(" + expr + ")) { "
               "printf(\"Assertion failed at line %d: %s\\n\", __LINE__, \"" + expr + "\"); "
               "exit(1); }";
    }
};
class Parser {
private:
    struct VariableInfo {
        bool isConst;
        ValueType type;
    };

    unordered_map<string, VariableInfo> symbolTable;
    vector<Token> tokens;
    size_t current;

    const Token& peek() const {
        return tokens[current];
    }

    const Token& previous() const {
        return tokens[current - 1];
    }

    bool isAtEnd() const {
        return peek().type == TokenType::END;
    }

    bool match(TokenType type) {
        if (peek().type == type) {
            advance();
            return true;
        }
        return false;
    }

    Token consume(TokenType type, const string& message) {
        if (peek().type == type) {
            return advance();
        }

        throw parseError(message);
    }

    Token advance() {
        if (!isAtEnd()) current++;
        return previous();
    }

    runtime_error parseError(const string& message) {
        return runtime_error(message + " at line " + to_string(peek().line) +
                           ", column " + to_string(peek().column));
    }

    ValueType parseTypeAnnotation() {
        if (match(TokenType::INT_TYPE)) {
            return ValueType::INTEGER;
        } else if (match(TokenType::FLOAT_TYPE)) {
            return ValueType::FLOAT;
        } else if (match(TokenType::STRING_TYPE)) {
            return ValueType::STRING;
        } else if (match(TokenType::BOOL_TYPE)) {
            return ValueType::BOOL;
        } else if (match(TokenType::NULL_TYPE)) {
            return ValueType::NULL_;
        }
        throw parseError("Expected type annotation");
    }

public:
    explicit Parser(vector<Token> tokens) : tokens(std::move(tokens)), current(0) {}

    vector<unique_ptr<ASTNode>> parse() {
        vector<unique_ptr<ASTNode>> statements;

        while (!isAtEnd()) {
            statements.push_back(parseStatement());
        }

        return statements;
    }

    unique_ptr<ASTNode> parseStatement() {
        if (match(TokenType::PRINT)) {
            return parsePrintStatement();
        } else if (match(TokenType::ASSERT)) {
            return parseAssertStatement();
        } else if (match(TokenType::LET) || match(TokenType::CONST)) {
            bool isConst = previous().type == TokenType::CONST;
            return parseVariableDeclaration(isConst);
        }

        throw parseError("Expected statement");
    }

    unique_ptr<PrintStatement> parsePrintStatement() {
        consume(TokenType::LPAREN, "Expected '(' after 'print'");
        auto expr = parseExpression();
        consume(TokenType::RPAREN, "Expected ')' after expression");
        consume(TokenType::SEMICOLON, "Expected ';' after statement");
        return make_unique<PrintStatement>(move(expr));
    }

    unique_ptr<AssertStatement> parseAssertStatement() {
        consume(TokenType::LPAREN, "Expected '(' after 'assert'");
        auto expr = parseExpression();
        consume(TokenType::RPAREN, "Expected ')' after expression");
        consume(TokenType::SEMICOLON, "Expected ';' after statement");
        return make_unique<AssertStatement>(move(expr));
    }

    unique_ptr<VariableDeclaration> parseVariableDeclaration(bool isConst) {
        Token identifier = consume(TokenType::IDENTIFIER, "Expected variable name");

        ValueType declaredType = ValueType::UNKNOWN;
        bool hasTypeAnnotation = false;
        if (match(TokenType::COLON)) {
            declaredType = parseTypeAnnotation();
            hasTypeAnnotation = true;
        }

        consume(TokenType::ASSIGN, "Expected '=' after variable name");
        auto initializer = parseExpression();
        consume(TokenType::SEMICOLON, "Expected ';' after variable declaration");

        if (hasTypeAnnotation) {
            ValueType initType = initializer->getType();
            if (initType != ValueType::UNKNOWN && initType != declaredType) {
                throw parseError("Type mismatch in variable declaration");
            }
        }

        symbolTable[identifier.value] = {isConst, hasTypeAnnotation ? declaredType : initializer->getType()};
        return make_unique<VariableDeclaration>(
            isConst, identifier.value, declaredType, hasTypeAnnotation, move(initializer));
    }

    unique_ptr<Expression> parseExpression() {
        return parseTernary();
    }

    unique_ptr<Expression> parseTernary() {
        auto expr = parseAssignment();

        if (match(TokenType::QUESTION)) {
            auto trueExpr = parseExpression();
            consume(TokenType::COLON, "Expected ':' in ternary operator");
            auto falseExpr = parseTernary();
            return make_unique<TernaryOperation>(move(expr), move(trueExpr), move(falseExpr));
        }

        return expr;
    }

    unique_ptr<Expression> parseAssignment() {
        auto expr = parseBinaryOperation(0);

        if (match(TokenType::ASSIGN)) {
            Token equals = previous();
            auto value = parseAssignment();

            if (auto var = dynamic_cast<VariableReference*>(expr.get())) {
                auto it = symbolTable.find(var->identifier);
                if (it != symbolTable.end() && it->second.isConst) {
                    throw parseError("Cannot assign to const variable '" + var->identifier + "'");
                }
                return make_unique<BinaryOperation>(equals, move(expr), move(value));
            }

            throw parseError("Invalid assignment target");
        }

        return expr;
    }

    unique_ptr<Expression> parseBinaryOperation(int minPrecedence) {
        auto left = parseUnary();

        while (true) {
            Token op = peek();
            int precedence = getOperatorPrecedence(op.type);

            if (precedence < minPrecedence || !isBinaryOperator(op.type)) {
                break;
            }

            advance();
            auto right = parseBinaryOperation(precedence + 1);

            left = make_unique<BinaryOperation>(op, move(left), move(right));
        }

        return left;
    }

    unique_ptr<Expression> parseUnary() {
        if (match(TokenType::MINUS)) {
            Token op = previous();
            auto expr = parsePrimary();
            return make_unique<UnaryOperation>(op, move(expr));
        } else if (match(TokenType::BIT_NOT)) {
            Token op = previous();
            auto expr = parsePrimary();
            return make_unique<UnaryOperation>(op, move(expr));
        }
        return parsePrimary();
    }

    unique_ptr<Expression> parsePrimary() {
        if (match(TokenType::INPUT)) {
            return make_unique<BuiltinCall>(TokenType::INPUT, nullptr);
        }
        else if (match(TokenType::LEN) || match(TokenType::SIZEOF)) {
            TokenType funcType = previous().type;
            auto arg = parsePrimary(); // 直接读取后续表达式作为参数
            return make_unique<BuiltinCall>(funcType, move(arg));
        }
        else if (match(TokenType::INTEGER) || match(TokenType::FLOAT) ||
                 match(TokenType::STRING) || match(TokenType::BOOL) ||
                 match(TokenType::NULL_)) {
            return make_unique<Literal>(previous());
        }
        else if (match(TokenType::IDENTIFIER)) {
            return make_unique<VariableReference>(previous().value);
        }
        else if (match(TokenType::LPAREN)) {
            auto expr = parseExpression();
            consume(TokenType::RPAREN, "Expected ')' after expression");
            return expr;
        }

        throw parseError("Expected expression");
    }

    bool isBinaryOperator(TokenType type) const {
        switch (type) {
            case TokenType::PLUS:
            case TokenType::MINUS:
            case TokenType::STAR:
            case TokenType::SLASH:
            case TokenType::PERCENT:
            case TokenType::LSHIFT:
            case TokenType::RSHIFT:
            case TokenType::URSHIFT:
            case TokenType::SPACESHIP:
            case TokenType::EQUAL:
            case TokenType::NOT_EQUAL:
            case TokenType::STRICT_EQUAL:
            case TokenType::STRICT_NOT_EQUAL:
            case TokenType::LESS:
            case TokenType::GREATER:
            case TokenType::LESS_EQUAL:
            case TokenType::GREATER_EQUAL:
            case TokenType::ASSIGN:
            case TokenType::IS:
            case TokenType::AS:
            case TokenType::BIT_AND:
            case TokenType::BIT_OR:
            case TokenType::BIT_XOR:
                return true;
            default:
                return false;
        }
    }

    int getOperatorPrecedence(TokenType type) const {
        switch (type) {
            case TokenType::ASSIGN:
                return 1;
            case TokenType::QUESTION:
                return 2;
            case TokenType::SPACESHIP:
                return 4;
            case TokenType::EQUAL:
            case TokenType::NOT_EQUAL:
            case TokenType::STRICT_EQUAL:
            case TokenType::STRICT_NOT_EQUAL:
            case TokenType::LESS:
            case TokenType::GREATER:
            case TokenType::LESS_EQUAL:
            case TokenType::GREATER_EQUAL:
                return 5;
            case TokenType::BIT_AND:
                return 6;
            case TokenType::BIT_XOR:
                return 7;
            case TokenType::BIT_OR:
                return 8;
            case TokenType::LSHIFT:
            case TokenType::RSHIFT:
            case TokenType::URSHIFT:
                return 9;
            case TokenType::PLUS:
            case TokenType::MINUS:
                return 10;
            case TokenType::STAR:
            case TokenType::SLASH:
            case TokenType::PERCENT:
                return 11;
            default:
                return 0;
        }
    }
};

class CodeGenerator {
public:
    string generate(const vector<unique_ptr<ASTNode>>& statements) {
        string code;

        code += "#include <stdio.h>\n";
        code += "#include <string.h>\n";
        code += "#include <stdlib.h>\n";
        code += "#include <stdbool.h>\n\n";

        code += "char* input() {\n";
        code += "    char buffer[1024];\n";
        code += "    if (fgets(buffer, sizeof(buffer), stdin) == NULL) {\n";
        code += "        return strdup(\"\");\n";
        code += "    }\n";
        code += "    buffer[strcspn(buffer, \"\\n\")] = '\\0';\n";
        code += "    return strdup(buffer);\n";
        code += "}\n\n";

        code += "int main() {\n";

        unordered_set<string> need_free;
        for (const auto& stmt : statements) {
            if (auto var_decl = dynamic_cast<VariableDeclaration*>(stmt.get())) {
                if (var_decl->initializer->getType() == ValueType::STRING) {
                    need_free.insert(var_decl->identifier);
                }
            }
            code += "    " + stmt->generateC() + "\n";
        }

        if (!need_free.empty()) {
            code += "\n    // Clean up\n";
            for (const auto& var : need_free) {
                code += "    free(" + var + ");\n";
            }
        }

        code += "    return 0;\n";
        code += "}\n";

        return code;
    }
};

class Compiler {
public:
    string compile(const string& source, const string& filename = "input") {
        Lexer lexer(source);
        lexer.setFilename(filename);
        auto tokens = lexer.tokenize();

        Parser parser(tokens);
        auto statements = parser.parse();

        CodeGenerator generator;
        return generator.generate(statements);
    }
};

// 主程序
int main(int argc, char* argv[]) {
    if (argc != 2) {
        cerr << "Usage: " << argv[0] << " <source_file>" << endl;
        return 1;
    }

    try {
        FILE* file = fopen(argv[1], "r");
        if (!file) {
            cerr << "Error: Could not open file " << argv[1] << endl;
            return 1;
        }

        fseek(file, 0, SEEK_END);
        long length = ftell(file);
        fseek(file, 0, SEEK_SET);

        string source(length, '\0');
        fread(&source[0], 1, length, file);
        fclose(file);

        Compiler compiler;
        string cCode = compiler.compile(source, argv[1]);
        cout << cCode << endl;

    } catch (const exception& e) {
        cerr << "Compilation error: " << e.what() << endl;
        return 1;
    }

    return 0;
}